package com.ybt.transaction;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;

import com.ybt.configration.IYBTConfigration;
import com.ybt.configration.YBTConfigration;
import com.ybt.configration.YBTRuntimeConfiguration;
import com.ybt.pub.XmlUtil;
import com.ybt.service.manager.ServiceManager;

public class TransactionMapping {
    private static Logger logger = Logger.getLogger(ServiceManager.class);
    private static String CONFIG_DIR = "transactionMapping" + File.separator
            + "mapping.xml";
    private Map<String, String> mapping;
    private static final String SEPARATE_CHAR = ":";

    private volatile static TransactionMapping manager;

    private TransactionMapping() {
        mapping = new ConcurrentHashMap<String, String>();

        CONFIG_DIR = YBTConfigration.getInstance().getProperty(
                IYBTConfigration.WORKFLOW_DEPLOY_PATH)
                + File.separator + CONFIG_DIR;

        loadFromLocal();
    }

    public static TransactionMapping getInstance() {
        if (manager == null) {
            synchronized (ServiceManager.class) {
                if (manager == null) {
                    manager = new TransactionMapping();
                }
            }
        }
        return manager;
    }

    /**
     * 根据服务名称，获取服务对象.
     * 
     * @param channel
     *            渠道名称
     * @param outCode
     *            外部交易码
     * @return 内部交易名称
     */
    public String getServiceWorkflow(String channel, String outCode) {
        String service = mapping.get(channel + TransactionMapping.SEPARATE_CHAR
                + outCode);
        if (service == null) {
            throw new RuntimeException(
                    "can't mapping the out transaction code to service workflow ["
                            + channel + TransactionMapping.SEPARATE_CHAR
                            + outCode + "]");
        }
        return service;

    }

    private void loadFromLocal() {

        File file = new File(CONFIG_DIR);
        if (!file.exists()) {
            throw new RuntimeException("can't find the configration file : "
                    + CONFIG_DIR);
        }

        try {
            Document doc = XmlUtil.loadXml(CONFIG_DIR, YBTRuntimeConfiguration
                    .getInstance().getConfigFileCharset());
            List<Element> channels = doc.getRootElement().elements("channel");
            for (Element ec : channels) {
                // 解析每个渠道
                String channel = ec.attributeValue("name");
                logger.debug("load transaction mapping for channel [" + channel
                        + "]");

                List<Element> ts = ec.elements("transaction");
                for (Element et : ts) {
                    //解析每个交易
                    String outCode = et.attributeValue("outCode");
                    String workflow = et.getTextTrim();
                    mapping.put(channel + TransactionMapping.SEPARATE_CHAR
                            + outCode, workflow);

                    logger.debug("load transaction mapping [" + channel
                            + TransactionMapping.SEPARATE_CHAR + outCode
                            + "---" + workflow + "]");
                }

            }
        } catch (Exception e) {
            throw new RuntimeException("parse configration file error : "
                    + CONFIG_DIR, e);
        }
    }
}
